package UtilsApplication;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ControllerApplication.AudioProcessingLocal;
import ModelApplication.Sound;

public class DetectNotes {


    static public List<Sound> detectNotes(Sound sound, AudioProcessingLocal audioProcessing,int zcrMethod) {

        List<Sound> detectedSounds = new ArrayList<Sound>();

        String methodName = "Cepstrum";

        if (zcrMethod==1) {
            methodName = "Analiza przejść przez zero";
        } else if (zcrMethod==2) {
            methodName = "Zliczanie maksimów";
        } else if (zcrMethod==3) {
            methodName = "Analiza przejść przez wartość progową";		
        }


        double [] origAudio = sound.getAudio();
        // final double DIFF = 10.0;
        final double MAX_FREQ = 1400;
        int countSamples = (int)sound.getWavFile().getSampleRate() / 20;
        final int SAMPLES = FourierUtil.checkInputLength( countSamples ) + countSamples;

        // double lastFreq = 0.0;
        List<Pair> tonesChanged = new ArrayList<Pair>();

        double [] audio;
        for(int k = 0; k < origAudio.length - 1; k += SAMPLES) {
            audio = Arrays.copyOfRange( origAudio, k, k + SAMPLES );
            double frequency = audioProcessing.findFundamentalFreq( detectedSounds, audio, sound, zcrMethod);

//            if(frequency > MAX_FREQ ) {
//                continue;
//            }

            //if(Math.abs(frequency - lastFreq) > DIFF) {
            float time = (float)k / (float)sound.getWavFile().getSampleRate();
            tonesChanged.add( new Pair(frequency, time,k) );
            System.out.println(tonesChanged.get( tonesChanged.size() - 1 ).toString());
            //}

            // lastFreq = frequency;
        }

        // lista wykrytych tonow
        Sound newAllSound = new Sound(null, sound.getWavFile(), null, methodName, sound.getName(), "wygenerowanyDzwiekCaly");
        List<Double> newAllAudio = new ArrayList<Double>();

        double [] valuedDouble = new double[origAudio.length];

        for(int i = 0; i < origAudio.length; i++) {

            boolean isFound = false;
            for(Pair pair : tonesChanged){
                if(pair.getPos() == i) {
                    valuedDouble[i] = pair.getFreq();
                    isFound = true;
                    break;
                }
            }

            if(!isFound) {
                valuedDouble[i] = 0;
            }
        }

        // wykryte czesstotliwosci
        Sound newSound1 =  new Sound(valuedDouble, sound.getWavFile(), null, methodName, sound.getName(), "czestotliwosci");
        newSound1.setChartType( ChartTypes.TIME_VALUE );
        detectedSounds.add(newSound1);

        for(int i = 0; i < tonesChanged.size(); i++) {             
            double time = 0;
            if(i == tonesChanged.size() - 1) {
                time = (origAudio.length / sound.getWavFile().getSampleRate()) -  tonesChanged.get(i).getTime();
            } else {
                time = tonesChanged.get(i + 1).getTime() - tonesChanged.get(i).getTime();
            }           
            if(time < 0) {
                continue;
            }


            double rate = sound.getWavFile().getSampleRate();
            double top = 0;
            for(int w = (int)(tonesChanged.get(i).getTime() * rate); w < (int)(tonesChanged.get(i).getTime() * rate) + (time * rate)/2; w++) {
                if(origAudio[w] > top) {
                    top = origAudio[w];
                }
            }

            double [] newAudio = HandleAudioUtil.createTone(
                    tonesChanged.get(i).getFreq(),
                    top,
                    (int)(time *sound.getWavFile().getSampleRate()) , 
                    (int)sound.getWavFile().getSampleRate() );
            Sound newSound =  new Sound(newAudio, sound.getWavFile(), null, methodName, sound.getName(), "wygenerowanyTonNr"+(i+1));
            newSound.setBaseFreq( tonesChanged.get(i).getFreq() );
            newSound.setExecutionTime( time );
            // detectedSounds.add(newSound);

            for(int z = 0; z < newAudio.length; z++) {
                newAllAudio.add( newAudio[z] );
            }

        } 

        newAllSound.setExecutionTime( (double)newAllAudio.size() / (double)sound.getWavFile().getSampleRate() );
        double [] tmpAudio = new double [newAllAudio.size()];
        for(int z = 0; z < tmpAudio.length; z++) {
            tmpAudio[z] = newAllAudio.get( z );
        }
        newAllSound.setAudio( tmpAudio );     
        detectedSounds.add(newAllSound);

        return detectedSounds;
    }
}
